<?php
/**
 * XPHP Framework
 *
 * LICENSE
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * @category	XPHP
 * @package		XPHP_Uri
 * @author		XWEB Dev Team
 * @copyright	Copyright (c) 2010-2011 XWEB. (http://xweb.vn)	-	Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 * @license		http://xphp.xweb.vn/license.html     GNU GPL License	-	http://framework.zend.com/license/new-bsd     New BSD License
 * @version		$Id: Uri.php 20109 2011-22-08 02:05:09 Mr.UBKey $
 */
/**
 * XPHP_Uri
 *
 * @category	XPHP
 * @package		XPHP_Uri
 * @author		Mr.UBKey
 * @link		http://xphp.xweb.vn/user_guide/xphp_uri.html
 */
class XPHP_Uri
{
    /**
     * http
     */
    const SCHEME_HTTP = 'http';
    /**
     * https
     */
    const SCHEME_HTTPS = 'https';
    protected $_urlDelimiter = '/';
    /**
     * REQUEST_URI
     * @var string;
     */
    protected $_requestUri;
    /**
     * BASEURL
     * @var string
     */
    protected $_baseUrl = null;
    /**
     * BASEPATH
     * @var string
     */
    protected $_basePath = null;
    /**
     * PATH_INFO
     * @var string
     */
    protected $_pathInfo = '';
    /**
     * Set REQUEST_URI
     *
     * Nếu không có Request Uri truyền vào lấy giá trị trong  $_SERVER['REQUEST_URI'],
     * $_SERVER['HTTP_X_REWRITE_URL'], hoặc $_SERVER['ORIG_PATH_INFO'] + $_SERVER['QUERY_STRING'].
     * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
     * @license   http://framework.zend.com/license/new-bsd     New BSD License
     * @param string $requestUri
     * @return XPHP_Uri
     */
    public function setRequestUri ($requestUri = null)
    {
        if ($requestUri === null) {
            if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // check this first so IIS will catch
                $requestUri = $_SERVER['HTTP_X_REWRITE_URL'];
            } // IIS7 with URL Rewrite: make sure we get the unencoded url (double slash problem) 
            elseif (isset($_SERVER['IIS_WasUrlRewritten']) &&
             $_SERVER['IIS_WasUrlRewritten'] == '1' &&
             isset($_SERVER['UNENCODED_URL']) && $_SERVER['UNENCODED_URL'] != '') {
                $requestUri = $_SERVER['UNENCODED_URL'];
            } elseif (isset($_SERVER['REQUEST_URI'])) {
                $requestUri = $_SERVER['REQUEST_URI'];
                // Http proxy reqs setup request uri with scheme and host [and port] + the url path, only use url path
                $schemeAndHttpHost = $this->getScheme() . '://' .
                 $this->getHttpHost();
                if (strpos($requestUri, $schemeAndHttpHost) === 0) {
                    $requestUri = substr($requestUri, 
                    strlen($schemeAndHttpHost));
                }
            } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI
                $requestUri = $_SERVER['ORIG_PATH_INFO'];
                if (! empty($_SERVER['QUERY_STRING'])) {
                    $requestUri .= '?' . $_SERVER['QUERY_STRING'];
                }
            } else {
                return $this;
            }
        } elseif (! is_string($requestUri)) {
            return $this;
        } else {
            // Set GET items, if available
            if (false !== ($pos = strpos($requestUri, '?'))) {
                // Get key => value pairs and set $_GET
                $query = substr($requestUri, $pos + 1);
                parse_str($query, $vars);
                $this->setQuery($vars);
            }
        }
        $this->_requestUri = $requestUri;
        return $this;
    }
    /**
     * Trả về REQUEST_URI
     * @return string
     */
    public function getRequestUri ()
    {
        if (empty($this->_requestUri)) {
            $this->setRequestUri();
        }
        return $this->_requestUri;
    }
    /**
     * Set BASEURL
     *
     * VD:
     * - /admin
     * - /app/index.php
     * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
     * @license   http://framework.zend.com/license/new-bsd     New BSD License
     * @param mixed $baseUrl
     * @return XPHP_Uri
     */
    public function setBaseUrl ($baseUrl = null)
    {
        if ((null !== $baseUrl) && ! is_string($baseUrl)) {
            return $this;
        }
        if ($baseUrl === null) {
            $filename = (isset($_SERVER['SCRIPT_FILENAME'])) ? basename(
            $_SERVER['SCRIPT_FILENAME']) : '';
            if (isset($_SERVER['SCRIPT_NAME']) &&
             basename($_SERVER['SCRIPT_NAME']) === $filename) {
                $baseUrl = $_SERVER['SCRIPT_NAME'];
            } elseif (isset($_SERVER['PHP_SELF']) &&
             basename($_SERVER['PHP_SELF']) === $filename) {
                $baseUrl = $_SERVER['PHP_SELF'];
            } elseif (isset($_SERVER['ORIG_SCRIPT_NAME']) &&
             basename($_SERVER['ORIG_SCRIPT_NAME']) === $filename) {
                $baseUrl = $_SERVER['ORIG_SCRIPT_NAME']; // 1and1 shared hosting compatibility
            } else {
                // Backtrack up the script_filename to find the portion matching
                // php_self
                $path = isset(
                $_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : '';
                $file = isset($_SERVER['SCRIPT_FILENAME']) ? $_SERVER['SCRIPT_FILENAME'] : '';
                $segs = explode('/', trim($file, '/'));
                $segs = array_reverse($segs);
                $index = 0;
                $last = count($segs);
                $baseUrl = '';
                do {
                    $seg = $segs[$index];
                    $baseUrl = '/' . $seg . $baseUrl;
                    ++ $index;
                } while (($last > $index) &&
                 (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos));
            }
            // Does the baseUrl have anything in common with the request_uri?
            $requestUri = $this->getRequestUri();
            if (0 === strpos($requestUri, $baseUrl)) {
                // full $baseUrl matches
                $this->_baseUrl = $baseUrl;
                return $this;
            }
            if (0 === strpos($requestUri, dirname($baseUrl))) {
                // directory portion of $baseUrl matches
                $this->_baseUrl = rtrim(dirname($baseUrl), '/');
                return $this;
            }
            $truncatedRequestUri = $requestUri;
            if (($pos = strpos($requestUri, '?')) !== false) {
                $truncatedRequestUri = substr($requestUri, 0, $pos);
            }
            $basename = basename($baseUrl);
            if (empty($basename) || ! strpos($truncatedRequestUri, $basename)) {
                // no match whatsoever; set it blank
                $this->_baseUrl = '';
                return $this;
            }
            // If using mod_rewrite or ISAPI_Rewrite strip the script filename
            // out of baseUrl. $pos !== 0 makes sure it is not matching a value
            // from PATH_INFO or QUERY_STRING
            if ((strlen($requestUri) >=
             strlen($baseUrl)) &&
             ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0))) {
                $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
            }
        }
        $this->_baseUrl = rtrim($baseUrl, '/');
        return $this;
    }
    /**
     * Trả về BASEURL để làm URL(liên kết)
     * <a href='$baseUrl/News/index'>News</a>
     * @return string
     */
    public function getBaseUrl ()
    {
        if (null === $this->_baseUrl) {
            $this->setBaseUrl();
        }
        return $this->_baseUrl;
    }
    /**
     * Set BASEPATH
     * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
     * @license   http://framework.zend.com/license/new-bsd     New BSD License
     * @param string|null $basePath
     * @return XPHP_Uri
     */
    public function setBasePath ($basePath = null)
    {
        if ($basePath === null) {
            $filename = (isset($_SERVER['SCRIPT_FILENAME'])) ? basename(
            $_SERVER['SCRIPT_FILENAME']) : '';
            $baseUrl = $this->getBaseUrl();
            if (empty($baseUrl)) {
                $this->_basePath = '';
                return $this;
            }
            if (basename($baseUrl) === $filename) {
                $basePath = dirname($baseUrl);
            } else {
                $basePath = $baseUrl;
            }
        }
        if (substr(PHP_OS, 0, 3) === 'WIN') {
            $basePath = str_replace('\\', '/', $basePath);
        }
        $this->_basePath = rtrim($basePath, '/');
        return $this;
    }
    /**
     * Trả về BASEPATH để làm đường đẫn tới file
     * <img src='$basePath/images/xphp.jpg' />
     *
     * @return string
     */
    public function getBasePath ()
    {
        if (null === $this->_basePath) {
            $this->setBasePath();
        }
        return $this->_basePath;
    }
    /**
     * Set PATH_INFO
     * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
     * @license   http://framework.zend.com/license/new-bsd     New BSD License
     * @param string|null $pathInfo
     * @return XPHP_Uri
     */
    public function setPathInfo ($pathInfo = null)
    {
        if ($pathInfo === null) {
            $baseUrl = $this->getBaseUrl();
            if (null === ($requestUri = $this->getRequestUri())) {
                return $this;
            }
            // Remove the query string from REQUEST_URI
            $pos = strpos($requestUri, '?');
            if ($pos) {
                $requestUri = substr($requestUri, 0, $pos);
            }
            if (null !== $baseUrl && ((! empty($baseUrl) &&
             0 === strpos($requestUri, $baseUrl)) || empty($baseUrl)) &&
             false === ($pathInfo = substr($requestUri, strlen($baseUrl)))) {
                // If substr() returns false then PATH_INFO is set to an empty string 
                $pathInfo = '';
            } elseif (null === $baseUrl ||
             (! empty($baseUrl) && false === strpos($requestUri, $baseUrl))) {
                $pathInfo = $requestUri;
            }
        }
        $this->_pathInfo = (string) $pathInfo;
        return $this;
    }
    /**
     * Trả về chuỗi nằm giữa BaseUrl và QueryString
     * @return string
     */
    public function getPathInfo ()
    {
        if (empty($this->_pathInfo)) {
            $this->setPathInfo();
        }
        return $this->_pathInfo;
    }
    /**
     * Lấy ra kiểu HTTP hoặc HTTPS
     * @return string
     */
    public function getScheme ()
    {
        return ($this->getServer('HTTPS') == 'on') ? self::SCHEME_HTTPS : self::SCHEME_HTTP;
    }
    /**
     * Trả về tên HOST và PORT.
     * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
     * @license   http://framework.zend.com/license/new-bsd     New BSD License
     * @return string
     */
    public function getHttpHost ()
    {
        $host = $this->getServer('HTTP_HOST');
        if (! empty($host)) {
            return $host;
        }
        $scheme = $this->getScheme();
        $name = $this->getServer('SERVER_NAME');
        $port = $this->getServer('SERVER_PORT');
        if (($scheme == self::SCHEME_HTTP && $port == 80) ||
         ($scheme == self::SCHEME_HTTPS && $port == 443)) {
            return $name;
        } else {
            return $name . ':' . $port;
        }
    }
    /**
     * Trả về IP của Client
     *
     * @param  boolean $checkProxy
     * @return string
     */
    public function getClientIp ($checkProxy = true)
    {
        if ($checkProxy && $this->getServer('HTTP_CLIENT_IP') != null) {
            $ip = $this->getServer('HTTP_CLIENT_IP');
        } else 
            if ($checkProxy && $this->getServer('HTTP_X_FORWARDED_FOR') != null) {
                $ip = $this->getServer('HTTP_X_FORWARDED_FOR');
            } else {
                $ip = $this->getServer('REMOTE_ADDR');
            }
        return $ip;
    }
    /**
     * Trả về thông số của SERVER
     * @param string $index
     * @return mixed string
     */
    public function getServer ($index)
    {
        if (isset($_SERVER[$index]))
            return $_SERVER[$index];
        else
            return false;
    }
    /**
     * Phân tích URI loại bỏ BASEPATH và trả về mảng
     * @param void
     * @return array
     */
    public function parseRequestUri ()
    {
        $basePath = explode($this->_urlDelimiter, $this->getBasePath());
        $requestUri = explode($this->_urlDelimiter, $this->getRequestUri());
        $requestUri = array_slice($requestUri, sizeof($basePath), 
        sizeof($requestUri) - sizeof($basePath));
        return $requestUri;
    }
}